package com.spring.beans.factory.support;

import com.spring.beans.BeansException;
import com.spring.beans.factory.DisposableBean;
import com.spring.beans.factory.ObjectFactory;
import com.spring.beans.factory.config.SingletonBeanRegistry;

import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: Asuka
 * @Description:
 * @create: 2025-04-13 20:05
 */


public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {


    /**
     * 一级缓存
     */
    private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();

    /**
     * 二级缓存
     */
    private ConcurrentHashMap<String, Object> earlySingletonObjects = new ConcurrentHashMap<>();

    /**
     * 三级缓存
     */
    private ConcurrentHashMap<String, ObjectFactory<?>> singletonFactories = new ConcurrentHashMap<>();


    private final ConcurrentHashMap<String, DisposableBean> disposableBeans = new ConcurrentHashMap<>();



    @Override
    public Object getSingleton(String beanName) {
        Object singletonObject = singletonObjects.get(beanName);
        if (singletonObject == null){
            singletonObject = earlySingletonObjects.get(beanName);
            if (singletonObject == null){
                ObjectFactory<?> singletonFacatory = singletonFactories.get(beanName);
                //如果三级缓存没拿到返回空
                //三级缓存拿到
                if (singletonFacatory != null){
                    singletonObject = singletonFacatory.getObject();
                    //从三级缓存放到二级缓存

                    earlySingletonObjects.put(beanName,singletonObject);
                    singletonFactories.remove(beanName);
                }
            }
        }


        return singletonObject;
    }

    @Override
    public void addSingleton(String beanName, Object singletonObject) {
        singletonObjects.put(beanName, singletonObject); // 1
        earlySingletonObjects.remove(beanName); // 2
        singletonFactories.remove(beanName); // 3
    }


    protected void addSingletonFactory(String beanName,ObjectFactory<?> singletonFactory){
        singletonFactories.put(beanName,singletonFactory);
    }

    public void registerDisposableBean(String beanName, DisposableBean bean) {
        disposableBeans.put(beanName, bean);
    }

    public void destroySingletons() {
        ArrayList<String> beanNames = new ArrayList<>(disposableBeans.keySet());
        for (String beanName : beanNames) {
            DisposableBean disposableBean = disposableBeans.remove(beanName);
            try {
                disposableBean.destroy();
            } catch (Exception e) {
                throw new BeansException("Destroy method on bean with name '" + beanName + "' threw an exception", e);
            }

        }

    }


}
